using System;
using System.Collections.Generic;
using Unity.Collections;
using UnityEngine;
using UnityEngine.UI;
/// <summary>
/// SFUI_ScrollRect组件[Show]
/// </summary>
public partial class SFUI_ScrollRect
{
    /// <summary>
    /// 子项总数
    /// </summary>
    public int itemTotalCount { get; private set; }

    /// <summary>
    /// 子项起始索引
    /// </summary>
    public int itemStartIndex { get; private set; }

    /// <summary>
    /// 布局spacing
    /// </summary>
    public Vector2 spacing { get; private set; }

    #region OnCaculateItemTotalCount 计算Item总数
    /// <summary>
    /// 计算Item总数
    /// </summary>
    /// <param name="_index">指定索引</param>
    /// <returns>true:有效数据,false:无效数据</returns>
    bool OnCalculateItemTotalCount(int _index = 0)
    {
        itemTotalCount = 0;
        itemStartIndex = 0;
        int? count = mFuncGetItemCount?.Invoke();
        if (count.HasValue)
        {
            itemTotalCount = count.Value;            
        }
        else
        {
            Debug.LogError($"FuncGetItemCount is null , it can't get item count.");
        }
        itemTotalCount = Mathf.Clamp(itemTotalCount, 0, int.MaxValue);
        if (itemTotalCount > 0)
        {
            if (mIsInfiniteLoop)
            {
                _index = _index % itemTotalCount;
            }
            itemStartIndex = Mathf.Clamp(_index, 0, itemTotalCount);
        }
        else
        {
            Debug.LogError($"Show Item Count must >0");
        }
        return itemTotalCount > 0;
    }
    #endregion

    #region ShowView 显示视图
    /// <summary>
    /// 是否运行LateUpdateRunning
    /// </summary>
    bool mIsLateUpdateRunning = false;
    /// <summary>
    /// 起始Item
    /// </summary>
    SFUI_ScrollRectItem mStartItem = null;
    /// <summary>
    /// 等待一帧
    /// </summary>
    bool mWaitFrame = false;
    /// <summary>
    /// 预加载数
    /// </summary>
    const int mPreAddNum = 3;
    /// <summary>
    /// 子项行或列最大值
    /// </summary>
    [SerializeField]
    [ReadOnly]
    int mItemRowOrColumnMaxCount = 0;
    /// <summary>
    /// 是否等待清除视图
    /// </summary>
    bool mIsWaitClearView = false;
    /// <summary>
    /// 是否在添加或删除Item
    /// </summary>
    bool mIsAddOrRecycleItem = false;
    /// <summary>
    /// 显示视图
    /// </summary>
    /// <param name="_index">指定索引</param>
    public void ShowView(int _index = 0)
    {
        OnCalculateItemTotalCount(_index);
        ClearView();        
        mIsLateUpdateRunning = itemTotalCount > 0;
    }
    #endregion

    #region ClearView 清除视图
    /// <summary>
    /// 清除视图
    /// </summary>
    public void ClearView()
    {
        mIsWaitClearView = true;
        mIsLateUpdateRunning = false;
    }

    /// <summary>
    /// 清除视图
    /// </summary>
    void OnClearView()
    {        
        mItemRowOrColumnMaxCount = 0;
        while (content.childCount > 0)
        {
            OnRecycleItem(content.GetChild(0));
        }
        GridLayoutGroup grid = mLayoutGroup as GridLayoutGroup;
        if (grid != null)
        {
            grid.constraint = GridLayoutGroup.Constraint.Flexible;
            grid.constraintCount = 0;
        }
        mStartItem = null;
        OnForceRebuildLayoutImmediate();
    }
    #endregion

    #region RefreshView 刷新在View中显示并符合条件的子项
    /// <summary>
    /// 刷新在View中显示并符合条件的子项
    /// </summary>
    /// <param name="_condition">条件</param>ss
    public void RefreshView(Func<SFUI_ScrollRectItem,bool> _condition)
    {
        if (content.childCount > 0)
        {
            foreach (Transform key in content)
            {
                var item = OnGetItem(key);
                if (_condition == null || _condition.Invoke(item))
                {
                    mActionUpdateItem?.Invoke(item);
                }
            }
            OnStopDrag();
        }
    }
    #endregion

    #region OnLateUpdateView LateUpdate更新视图
    /// <summary>
    /// LateUpdate更新视图
    /// </summary>
    void OnLateUpdateView()
    {
        if (mIsWaitClearView && !mIsAddOrRecycleItem)
        {
            OnClearView();
            mIsWaitClearView = false;
        }
        else if (OnCanLateUpdateView())
        {
            mIsAddOrRecycleItem = true;
            if (mItemRowOrColumnMaxCount <= 0)
            {                
                content.anchoredPosition = Vector2.zero;
                if (OnCalculateRowOrColumnMaxCount())
                {
                    OnFillContent();
                }                
            }
            else if (mStartItem != null)
            {
                enabled = false;
                Vector2 pos = mStartItem.LocationLeftOrTopContentAnchoredPosition();
                content.anchoredPosition = pos;
                OnForceRebuildLayoutImmediate();
                StopMovement();
                OnStopDrag();
                mStartItem = null;
                mWaitFrame = true;
                enabled = true;
            }
            else if (mWaitFrame)
            {
                mWaitFrame = false;
            }
            else if (OnPreAddLast() || OnPreAddFirst())
            {
                OnStopDrag();
                mWaitFrame = true;
            }
            else if (OnRecycleLast() || OnRecycleFirst())
            {
                OnStopDrag();
                mWaitFrame = true;
            }
            mIsAddOrRecycleItem = false;
        }
    }

    /// <summary>
    /// 计算RowOrColumn最大数
    /// </summary>
    bool OnCalculateRowOrColumnMaxCount()
    {
        switch (mLayoutGroupType)
        {
            case enSFUI_ScrollRect_LayoutGroupType.HorizontalOrVerticalLayoutGroup:
                mItemRowOrColumnMaxCount = 1;
                HorizontalOrVerticalLayoutGroup hvg = mLayoutGroup as HorizontalOrVerticalLayoutGroup;
                spacing = new Vector2(hvg.spacing, hvg.spacing);
                mStartItem = OnCreateItem(itemStartIndex, itemStartIndex);
                break;
            case enSFUI_ScrollRect_LayoutGroupType.GridLayoutGroup:
                if (content.childCount <= 0)
                {
                    mStartItem = OnCreateItem(itemStartIndex, itemStartIndex);
                }
                else
                {
                    List<int> pos = new List<int>();
                    int val = 0;
                    Action actRCMC = null;
                    switch (mScrollMode)
                    {
                        case enSFUI_ScrollRect_ScrollMode.Horizontal:
                            actRCMC = () =>
                            {
                                mItemRowOrColumnMaxCount = Mathf.Max(1, pos.Count);
                                GridLayoutGroup grid = mLayoutGroup as GridLayoutGroup;
                                grid.constraintCount = mItemRowOrColumnMaxCount;
                                grid.constraint = GridLayoutGroup.Constraint.FixedRowCount;
                                spacing = grid.spacing;
                            };
                            foreach (RectTransform key in content)
                            {
                                val = Mathf.CeilToInt(key.anchoredPosition.y);
                                if (pos.Contains(val))
                                {//当Y重复或content的数量是最大数量
                                    actRCMC.Invoke();
                                    break;
                                }
                                else
                                {
                                    pos.Add(val);
                                }
                            }
                            break;
                        case enSFUI_ScrollRect_ScrollMode.Vertical:
                            actRCMC = () =>
                            {
                                mItemRowOrColumnMaxCount = Mathf.Max(1, pos.Count);
                                GridLayoutGroup grid = mLayoutGroup as GridLayoutGroup;
                                grid.constraintCount = mItemRowOrColumnMaxCount;
                                grid.constraint = GridLayoutGroup.Constraint.FixedColumnCount;
                                spacing = grid.spacing;
                            };
                            foreach (RectTransform key in content)
                            {
                                val = Mathf.CeilToInt(key.anchoredPosition.x);
                                if (pos.Contains(val))
                                {//当X重复或content的数量是最大数量
                                    actRCMC.Invoke();
                                    break;
                                }
                                else
                                {
                                    pos.Add(val);
                                }
                            }
                            break;
                    }
                    if (mItemRowOrColumnMaxCount <= 0)
                    {
                        if (!OnAddLast())
                        {
                            if (!OnAddFirst())
                            {
                                if (pos.Count == itemTotalCount)
                                {
                                    actRCMC.Invoke();
                                }
                            }
                        }
                    }
                    else
                    {
                        int first = OnGetItem(content.GetChild(0)).FirstAlignmentSupplement(mItemRowOrColumnMaxCount);
                        int end = OnGetItem(content.GetChild(content.childCount - 1)).LastAlignmentSupplement(mItemRowOrColumnMaxCount);
                        for (int i = 0; i < first; i++)
                        {
                            OnAddFirst();
                        }
                        for (int i = 0; i < end; i++)
                        {
                            OnAddLast();
                        }
                    }
                    OnForceRebuildLayoutImmediate();
                }
                break;
        }
        return mItemRowOrColumnMaxCount > 0;
    }

    /// <summary>
    /// 强制重绘
    /// </summary>
    void OnForceRebuildLayoutImmediate()
    {
        Rebuild(CanvasUpdate.Prelayout);
        Rebuild(CanvasUpdate.PostLayout);
        LayoutRebuilder.ForceRebuildLayoutImmediate(content);
    }

    /// <summary>
    /// 填充满Content
    /// </summary>
    void OnFillContent()
    {
        bool isContinue = true;
        //补全视图内节点
        while (isContinue && !(OnFullContentHorizontal() && OnFullContentVertical()))
        {
            isContinue = OnAddLast();
            if (!isContinue)
            {
                isContinue = OnAddFirst();
            }
            OnForceRebuildLayoutImmediate();
        }
        isContinue = true;
        //对齐视图内节点
        do {
            isContinue = true;
            var first = OnGetItem(content.GetChild(0));
            if (first.IsFirstAlignment(mItemRowOrColumnMaxCount))
            {
                var last = OnGetItem(content.GetChild(content.childCount - 1));
                if (last.IsLastAlignment(mItemRowOrColumnMaxCount))
                {
                    isContinue = false;
                }
                else
                {
                    isContinue = OnAddLast();
                }
            }
            else
            {
                isContinue = OnAddFirst();
            }
        }
        while (isContinue);
    }

    /// <summary>
    /// 是否可更视图
    /// </summary>
    /// <returns>true:可,false:不可</returns>
    bool OnCanLateUpdateView()
    {
        return mIsLateUpdateRunning;
    }

    /// <summary>
    /// 向首部添加子项
    /// </summary>
    /// <returns>true:添加成功,false:添加失败</returns>
    bool OnAddFirst()
    {
        bool result = false;
        int orderIndex = 0;
        int index = OnPrevItemIndex(content.GetChild(0), out orderIndex);
        if (index >= 0)
        {
            SFUI_ScrollRectItem item = OnCreateItem(index, orderIndex);
            item.transform.SetAsFirstSibling();
            result = true;
        }
        return result;
    }

    /// <summary>
    /// 向尾部添加子项
    /// </summary>
    /// <returns>true:添加成功,false:添加失败</returns>
    bool OnAddLast()
    {
        bool result = false;
        int orderIndex = 0;
        int index = OnNextItemIndex(content.GetChild(content.childCount - 1), out orderIndex);
        if (index >= 0 && index < itemTotalCount)
        {
            SFUI_ScrollRectItem item = OnCreateItem(index, orderIndex);
            item.transform.SetAsLastSibling();
            result = true;
        }
        return result;
    }

    /// <summary>
    /// 获得下一个索引
    /// </summary>
    /// <param name="_item">子项</param>
    /// <param name="_orderIndex">编号索引</param>
    /// <returns>索引</returns>
    int OnNextItemIndex(Transform _item, out int _orderIndex)
    {
        SFUI_ScrollRectItem item = OnGetItem(_item);
        _orderIndex = item.orderIdx + 1;
        int index = item.dataIdx + 1;
        if (itemTotalCount <= index)
        {
            if (mIsInfiniteLoop)
            {
                index -= itemTotalCount;
            }
            else
            {
                index = -1;
            }
        }
        return index;
    }

    /// <summary>
    /// 获得上一个索引
    /// </summary>
    /// <param name="_item">子项</param>
    /// <returns>索引</returns>
    int OnPrevItemIndex(Transform _item, out int _orderIndex)
    {
        SFUI_ScrollRectItem item = OnGetItem(_item);
        _orderIndex = item.orderIdx - 1;
        int index = item.dataIdx - 1;
        if (index < 0)
        {
            if (mIsInfiniteLoop)
            {
                index += itemTotalCount;
            }
            else
            {
                index = -1;
            }
        }
        return index;
    }

    /// <summary>
    /// 是否Horizontal填满Content
    /// </summary>
    /// <returns>true:填满,false:未填满</returns>
    bool OnFullContentHorizontal()
    {
        return (!horizontal || content.rect.width > viewRect.rect.width);
    }

    /// <summary>
    /// 是否Vertical填满Content
    /// </summary>
    /// <returns>true:填满,false:未填满</returns>
    bool OnFullContentVertical()
    {
        return !vertical || content.rect.height > viewRect.rect.height;
    }

    /// <summary>
    /// 尾部预加载
    /// </summary>
    /// <returns>true:加载子项，false:未加载子项</returns>
    bool OnPreAddLast()
    {        
        var last = OnGetItem(content.GetChild(content.childCount - 1));
        bool result = last.CanPreAddLast(mPreAddNum);
        if (result)
        {
            result = OnAddLast();
            if (result)
            {//如果能尾部预加载，则看是否是对齐尾部
                OnForceRebuildLayoutImmediate();
                bool isEnd = false;
                do
                {
                    isEnd = false;
                    last = OnGetItem(content.GetChild(content.childCount - 1));
                    if (last.IsLastAlignment(mItemRowOrColumnMaxCount))
                    {
                        isEnd = true;
                    }
                    else
                    {
                        isEnd = !OnAddLast();                        
                    }
                    OnForceRebuildLayoutImmediate();
                }
                while (!isEnd);
            }            
        }
        return result;
    }

    /// <summary>
    /// 首部预加载
    /// </summary>
    /// <returns>true:加载子项，false:未加载子项</returns>
    bool OnPreAddFirst()
    {
        var first = OnGetItem(content.GetChild(0));
        bool result = first.CanPreAddFirst(mPreAddNum);
        Vector2 beforeAnchor = new Vector2(content.rect.width,content.rect.height);
        Vector2 afterAnchor = beforeAnchor;
        if (result)
        {
            result = OnAddFirst();
            if (result)
            {//如果能尾部预加载，则看是否是对齐尾部
                OnForceRebuildLayoutImmediate();
                bool isEnd = false;
                do
                {
                    isEnd = false;
                    first = OnGetItem(content.GetChild(0));
                    if (first.IsFirstAlignment(mItemRowOrColumnMaxCount))
                    {
                        isEnd = true;
                    }
                    else
                    {
                        isEnd = !OnAddFirst();
                    }
                    OnForceRebuildLayoutImmediate();
                }
                while (!isEnd);

                afterAnchor = new Vector2(content.rect.width, content.rect.height);
                Vector2 offset = Vector2.zero;
                switch (scrollMode)
                {
                    case enSFUI_ScrollRect_ScrollMode.Horizontal:
                        offset = beforeAnchor - afterAnchor;
                        break;
                    case enSFUI_ScrollRect_ScrollMode.Vertical:
                        offset = afterAnchor - beforeAnchor;
                        break;
                }
                if (offset != Vector2.zero)
                {
                    content.anchoredPosition += offset;
                    OnForceRebuildLayoutImmediate();                    
                }
            }                 
        }        
        return result;
    }

    /// <summary>
    /// 尾部回收
    /// </summary>
    /// <returns>true:回收子项，false:未回收子项</returns>
    bool OnRecycleLast()
    {
        var last = OnGetItem(content.GetChild(content.childCount - 1));
        bool result = last.CanRecycleLast(mPreAddNum);
        if (result)
        {
            OnRecycleItem(last.transform);
            OnForceRebuildLayoutImmediate();
            //如果能尾部预加载，则看是否是对齐尾部                
            bool isEnd = false;
            do
            {
                isEnd = false;
                last = OnGetItem(content.GetChild(content.childCount - 1));
                if (last.IsLastAlignment(mItemRowOrColumnMaxCount))
                {
                    isEnd = true;
                }
                else
                {
                    OnRecycleItem(last.transform);                    
                }
                OnForceRebuildLayoutImmediate();
            }
            while (!isEnd);
        }
        return result;
    }

    /// <summary>
    /// 首部回收
    /// </summary>
    /// <returns>true:回收子项，false:未回收子项</returns>
    bool OnRecycleFirst()
    {
        var first = OnGetItem(content.GetChild(0));
        bool result = first.CanRecycleFirst(mPreAddNum);
        Vector2 beforeAnchor = new Vector2(content.rect.width, content.rect.height);
        Vector2 afterAnchor = beforeAnchor;
        if (result)
        {
            OnRecycleItem(first.transform);
            OnForceRebuildLayoutImmediate();
            bool isEnd = false;
            do
            {
                isEnd = false;
                first = OnGetItem(content.GetChild(0));
                if (first.IsFirstAlignment(mItemRowOrColumnMaxCount))
                {
                    isEnd = true;
                }
                else
                {
                    OnRecycleItem(first.transform);
                }
                OnForceRebuildLayoutImmediate();
            }
            while (!isEnd);

            afterAnchor = new Vector2(content.rect.width, content.rect.height);
            Vector2 offset = Vector2.zero;
            switch (scrollMode)
            {
                case enSFUI_ScrollRect_ScrollMode.Horizontal:
                    offset = beforeAnchor - afterAnchor;
                    break;
                case enSFUI_ScrollRect_ScrollMode.Vertical:
                    offset = afterAnchor - beforeAnchor;
                    break;
            }
            if (offset != Vector2.zero)
            {
                content.anchoredPosition += offset;
                OnForceRebuildLayoutImmediate();
            }
        }
        return result;
    }
    #endregion
}
